﻿using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using AjaxControlToolkit;

namespace PortalCurriculo.Util.CustomControls
{
    public class MaskEditValidator : MaskedEditValidator
    {
        private string CssError { get; set; }
        public new event EventHandler<ServerValidateEventArgs> MaskedEditServerValidator;

        protected override bool EvaluateIsValid()
        {
            var maskExt = (MaskedEdit)FindControl(ControlExtender);
            var target = (TextBox)maskExt.FindControl(ControlToValidate);
            base.ErrorMessage = "";
            base.Text = "";
            bool ok = true;

            switch (maskExt.Type)
            {
                case MaskedEdit.MaskedEditType.DateTime:
                case MaskedEdit.MaskedEditType.None:
                case MaskedEdit.MaskedEditType.Number:
                case MaskedEdit.MaskedEditType.Time:
                    return base.EvaluateIsValid();
            }

            ok = ValidateEmptyData();

            if (ok)
                ok = ValidateRegularExpression();

            if (ok)
                ok = ValidateData();

            if (ok)
                ok = ServerValidate();

            if (!ok)
            {
                string script = "MaskedEditSetCssClass(" + this.ClientID + ",'" + CssError + "');";
                ScriptManager.RegisterStartupScript(this, typeof(MaskedEditValidator), "MaskedEditServerValidator_" + this.ID, script, true);
            }

            return ok;
        }

        private bool ServerValidate()
        {
            var maskExt = (MaskedEdit)FindControl(ControlExtender);
            var target = (TextBox)maskExt.FindControl(ControlToValidate);
            bool ok = true;

            if (MaskedEditServerValidator != null)
            {
                var serverValidateEventArgs = new ServerValidateEventArgs(target.Text, true);

                MaskedEditServerValidator(target, serverValidateEventArgs);
                ok = serverValidateEventArgs.IsValid;
                if (!ok)
                {
                    CssError = maskExt.OnInvalidCssClass;
                    ErrorMessage = this.InvalidValueMessage;
                    base.Text = string.IsNullOrEmpty(this.InvalidValueBlurredMessage) ? base.ErrorMessage : this.InvalidValueBlurredMessage;
                }
            }

            return ok;
        }

        private bool ValidateData()
        {
            var maskExt = (MaskedEdit)FindControl(ControlExtender);
            var target = (TextBox)maskExt.FindControl(ControlToValidate);
            bool ok = true;

            if (target.Text.Length != 0)
            {
                switch (maskExt.Type)
                {
                    case MaskedEdit.MaskedEditType.CPF:
                        ok = ValidateCPF(target.Text);
                        break;
                    case MaskedEdit.MaskedEditType.CNPJ:
                        ok = ValidateCNPJ(target.Text);
                        break;
                    case MaskedEdit.MaskedEditType.Date:
                        ok = ValidateHelper.ValidateDate(target.Text, maskExt.Culture);
                        break;
                    case MaskedEdit.MaskedEditType.Birthday:
                        ok = ValidateHelper.ValidateBirthday(target.Text, maskExt.Culture);
                        break;
                }

                if (!ok)
                {
                    base.ErrorMessage = this.InvalidValueMessage;
                    base.Text = string.IsNullOrEmpty(this.InvalidValueBlurredMessage) ? base.ErrorMessage : this.InvalidValueBlurredMessage;
                    CssError = maskExt.OnInvalidCssClass;
                }
            }

            return ok;
        }

        private static bool ValidateCPF(string cpf)
        {
            var multiplicador1 = new [] { 10, 9, 8, 7, 6, 5, 4, 3, 2 };
            var multiplicador2 = new [] { 11, 10, 9, 8, 7, 6, 5, 4, 3, 2 };

            cpf = cpf.Trim();
            cpf = cpf.Replace(".", "").Replace("-", "");

            if (cpf.Length != 11)
                return false;

            string tempCpf = cpf.Substring(0, 9);
            int soma = 0;

            for (int i = 0; i < 9; i++)
            {
                soma += int.Parse(tempCpf[i].ToString()) * multiplicador1[i];
            }

            int resto = soma % 11;

            if (resto < 2)
                resto = 0;
            else
                resto = 11 - resto;

            string digito = resto.ToString();
            tempCpf = tempCpf + digito;

            soma = 0;

            for (int i = 0; i < 10; i++)
            {
                soma += int.Parse(tempCpf[i].ToString()) * multiplicador2[i];
            }

            resto = soma % 11;

            if (resto < 2)
                resto = 0;
            else
                resto = 11 - resto;

            digito = digito + resto.ToString();

            return cpf.EndsWith(digito);
        }

        private static bool ValidateCNPJ(string cnpj)
        {
            var multiplicador1 = new int[12] { 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2 };
            var multiplicador2 = new int[13] { 6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2 };

            cnpj = cnpj.Trim();
            cnpj = cnpj.Replace(".", "").Replace("-", "").Replace("/", "");

            if (cnpj.Length != 14)
                return false;

            string tempCnpj = cnpj.Substring(0, 12);
            int soma = 0;

            for (int i = 0; i < 12; i++)
            {
                soma += int.Parse(tempCnpj[i].ToString()) * multiplicador1[i];
            }

            int resto = (soma % 11);

            if (resto < 2)
                resto = 0;
            else
                resto = 11 - resto;

            string digito = resto.ToString();
            tempCnpj = tempCnpj + digito;

            soma = 0;

            for (int i = 0; i < 13; i++)
            {
                soma += int.Parse(tempCnpj[i].ToString()) * multiplicador2[i];
            }

            resto = (soma % 11);

            if (resto < 2)
                resto = 0;
            else
                resto = 11 - resto;

            digito = digito + resto.ToString();

            return cnpj.EndsWith(digito);
        }

        private bool ValidateRegularExpression()
        {
            var maskExt = (MaskedEdit)FindControl(ControlExtender);
            var target = (TextBox)maskExt.FindControl(ControlToValidate);

            if (target.Text.Length != 0 && this.ValidationExpression.Length != 0)
            {
                try
                {
                    var regex = new System.Text.RegularExpressions.Regex(this.ValidationExpression);
                    return regex.IsMatch(target.Text);
                }
                catch
                {
                    return false;
                }
            }

            return true;
        }

        private bool ValidateEmptyData()
        {
            var maskExt = (MaskedEdit)FindControl(ControlExtender);
            var target = (TextBox)maskExt.FindControl(ControlToValidate);

            if (!this.IsValidEmpty)
            {
                if (target.Text.Trim() == this.InitialValue)
                {
                    base.ErrorMessage = this.EmptyValueMessage;
                    base.Text = string.IsNullOrEmpty(this.EmptyValueBlurredText) ? base.ErrorMessage : this.EmptyValueBlurredText;
                    CssError = maskExt.OnInvalidCssClass;
                    return false;
                }
            }

            return true;
        }
    }
}
